using System;
using System.Diagnostics;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using System.Collections.Generic;
using DE.Sdc.SharePoint.SPContentStructure.Common;

namespace DE.Sdc.SharePoint.SPContentStructure.Import
{
    [Serializable]
    [XmlType(AnonymousType = true, Namespace = DeploymentConstants.Namespace)]
    [XmlRoot(Namespace = DeploymentConstants.Namespace, IsNullable = false)]
    public partial class Item : BaseItem<Folder>, IImportDefinition<SPListItem, SPFolder>
    {
        private File _file;
        
        private bool _approve;

        /// <remarks/>
        [XmlAttribute]
        public bool Approve
        {
            get
            {
                return _approve || _file != null && _file.FileAction == FileActionType.Approve;
            }
            set
            {
                _approve = value;
            }
        }

        [XmlElement]
        public File File
        {
            get { return _file; }
            set
            {
                _file = value;
                _file.Item = this;
            }
        }

        public bool FileSpecified
        {
            get { return !(_file is Page); }
        } 

        [XmlElement]
        public Page Page
        {
            get { return _file as Page; }
            set
            {
                _file = value;
                _file.Item = this;
            }
        }

        [XmlIgnore]
        public List List
        {
            get
            {
                HierarchicalElement<Folder> parent = Parent;

                while (parent != null && !(parent is List))
                {
                    parent = parent.Parent;
                }

                return parent as List;
            }
        }

        

        //[XmlElement(typeof(PowershellNodes))]
        //public PowershellNodes PowerShellNodes { get; set; }

        [XmlIgnore]
        public SPListItem UpdatedSPObject { get; internal set; }

        protected override bool IsNewVersion(object sharePointObject)
        {
            if (sharePointObject == null || Version == 0)
                return true;

            SPListItem item = (SPListItem)sharePointObject;
            Trace.WriteLine("Check version number for item '" + item.Url + "'", "ContentStructureImporter:ImportItem");
            
            if (item.Properties.ContainsKey(DeploymentConstants.ContentStructureVersion))
            {
                int currentVersion = (int)item.Properties[DeploymentConstants.ContentStructureVersion];
                Trace.WriteLine("Current version is " + currentVersion + ", new version is " + Version + " for item '" + item.Url + "'", "ContentStructureImporter:ImportItem");
                return Version > currentVersion;
            }

            return true;
        }

        protected override void SetNewVersion(object sharePointObject)
        {
            if (sharePointObject == null || Version == 0)
                return;

            SPListItem item = (SPListItem)sharePointObject;
            if (item.Properties.ContainsKey(DeploymentConstants.ContentStructureVersion))
                item.Properties[DeploymentConstants.ContentStructureVersion] = Version;
            else
                item.Properties.Add(DeploymentConstants.ContentStructureVersion, Version);
        }

        /// <summary>
        /// Adds, Replaces, Deletes, Modifies or Moves a item in a given folder
        /// </summary>
        /// <param name="item">A item based on the itemDefinition or null</param>
        /// <param name="parentFolder">The parent folder where to import the item</param>
        public void ImportDefinition(SPListItem item, SPFolder parentFolder)
        {
            Trace.WriteLine(
                "Try to import item '" + Title + "' with url '" + AbsoluteUrl + "'.",
                "ContentStructureImporter:ImportItem");
           
            Title = DeploymentHelper.Resolve(Title, parentFolder.ParentWeb.Locale);
            Url = DeploymentHelper.Resolve(Url, parentFolder.ParentWeb.Locale);
            bool fileUpdated = false;
            DeploymentContext.Current.CurrentObjectType = DeploymentContext.DeploymentObjects.Item;

            if (Action == ActionType.AddOrUpdate || Action == ActionType.Replace)
            {
                
                //if Versioned , switch to Version Processing
                
                
                SPFile file;
                if (File != null && item != null && item.File != null)
                {
                    file = item.File;
                    File.UndoCheckout(file);

                    DeploymentContext.Current.File = item.File;
                    DeploymentContext.Current.FileDefinition = File;    
                }

                if (Action == ActionType.AddOrUpdate && item == null || (Action < ActionType.AddOrUpdateOrReplace && IsNewVersion(item)))
                {
                    item = AddOrUpdateItem(item, parentFolder, DeploymentContext.Current.ListDefinition.PrimaryKeyFieldsArray);
                    file = item.File;
                    if (file != null)
                        fileUpdated = true;
                }
            }
            else if (Action == ActionType.Delete)
            {
                if (item != null)
                    item.Delete();
                return;
            }

            SetNewVersion(item);

            DeploymentContext.Current.Item = item;
            DeploymentContext.Current.ItemDefinition = this;

            if (!fileUpdated && item != null && File != null && File.Action == ActionType.Replace)
            {
                File.ImportDefinition(item.File, parentFolder, false);
                item = File.UpdatedSPObject.Item;
            }

            if (Action != ActionType.None &&
                Action <= ActionType.AddOrUpdateOrReplace)
            {
                //if (item != null && File != null && item.File != null)
                //    File.Checkout(item.File);

                Properties.Modify(item);

                //if (file != null)
                //{
                //    if (Page != null)
                //        Page.ImportDefinition(file, parentFolder);
                //    else
                //        File.ImportDefinition(file, parentFolder);
                //}
            }

            
            
            if (File == null && Approve)
                ApproveItem(item);
            else if (File != null && item != null && item.File != null)
                File.ChangeFileLevel(item.File, this);

            

            Trace.WriteLine(
                "Item '" + Title + "' with url '" + AbsoluteUrl + "' imported.",
                "ContentStructureImporter:ImportItem");

            UpdatedSPObject = item;
        }

        /// <summary>
        /// Creates or replaces an item in a given folder
        /// </summary>
        /// <param name="item"></param>
        /// <param name="parentFolder">The parent folder where to create or replace the item</param>
        /// <param name="primaryKeyFields"></param>
        /// <returns></returns>
        internal SPListItem AddOrUpdateItem(SPListItem item, SPFolder parentFolder, string[] primaryKeyFields)
        {
            Trace.WriteLine("Try to create or replace item '" + Title + "' with url '" + AbsoluteUrl + "'.", "ContentStructureImporter:CreateOrReplaceItem");

            string filePath = null;

            try
            {
                if (File != null)
                {
                    File.ImportDefinition(item != null ? item.File : null, parentFolder, false);
                    return File.UpdatedSPObject != null ? File.UpdatedSPObject.Item : null;
                }
                else
                {
                    string itemUrl = Url;
                    if (string.IsNullOrEmpty(itemUrl))
                        itemUrl = parentFolder.ServerRelativeUrl.TrimEnd('/');

                    //var query = new SPQuery();
                    //query.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>" + itemDefinition.Title + "</Value></Eq></Where><OrderBy><FieldRef Name='Modified' Ascending='False' /></OrderBy>";
                    //query.Folder = parentFolder;
                    //var list = parentFolder.ParentWeb.Lists[parentFolder.ParentListId];
                    var listItems = GetListItems(primaryKeyFields, parentFolder, this);

                    if (Action == ActionType.Replace && listItems != null)
                    {
                        for (var i = listItems.Count - 1; i >= 0; i--)
                            listItems[i].Delete();
                    }
                    else if (listItems != null && (Action == ActionType.AddOrUpdate && listItems.Count > 0))
                        return listItems[0];
                    else if (listItems != null && listItems.Count > 0)
                        return null;
                    return parentFolder.ParentWeb.Lists[parentFolder.ParentListId].Items.Add(itemUrl, SPFileSystemObjectType.File, Title);
                }
            }
            catch (ContentStructureException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new ContentStructureException(
                    "Error while importing file '" + filePath + "'", ex);
            }
            finally
            {
                Trace.WriteLine("item '" + Title + "' with url '" + AbsoluteUrl + "' created or replaced.", "ContentStructureImporter:CreateOrReplaceItem");
            }
        }

        private static bool GetUndoCheckoutParameter(IBaseItem item)
        {
            if (item is List)
                return ((List)item).UndoFileCheckout;

            return false;
        }
    }
}